#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <stdbool.h>
#include <float.h>

#define C2 (1.0/(1.0*2.0))
#define C3 (1.0/(1.0*2.0*3.0))
#define C4 (1.0/(1.0*2.0*3.0*4.0))
#define C5 (1.0/(1.0*2.0*3.0*4.0*5.0))

void check_double( double f)
{
    if ( isinf(f) )
    {
        printf("f is inf\n");
    }

    if ( isnan(f) )
    {
        printf("f is not an number\n");
    }
}

void print_const()
{
    printf("\nrun %s()\n",__func__);

    double fac[]=
    {
        0x1.ffffffffffdbdp-2,
        0x1.555555555543cp-3,
        0x1.55555cf172b91p-5,
        0x1.1111167a4d017p-7
    };
    for (int i=0;i<sizeof(fac)/sizeof(fac[0]);i++)
    {
        double f=fac[i];
        printf("%.20lf\n",f);
    }

    double cs[]={C2,C3,C4,C5};
    int32_t *p;
    p=(int32_t*)(cs+0);  printf("C2={%d,%d}\n", p[0],p[1]);
    p=(int32_t*)(cs+1);  printf("C3={%d,%d}\n", p[0],p[1]);
    p=(int32_t*)(cs+2);  printf("C4={%d,%d}\n", p[0],p[1]);
    p=(int32_t*)(cs+3);  printf("C5={%d,%d}\n", p[0],p[1]);

    {
        double f=0x1.8p45;
        int32_t *p=(int32_t*)(&f);  printf("1.8p45={%d,%d}\n", p[0],p[1]);
    }

    {
        double f=-0x1.8p45;
        int32_t *p=(int32_t*)(&f);  printf("-1.8p45={%d,%d}\n", p[0],p[1]);
    }
}

#define INF_TEST(h,l) \
    u.i[1]= (h << 20);  u.i[0]= l; \
    printf("f=%lf,\t",u.d);   \
    /*check_double(u.d); */   \
    f=u.d * RLN2;             \
    printf("f*RLN2=%lf\n",f); \
    /* check_double(u.d); */

void test_float()
{
    printf("\nrun %s()\n",__func__);

    union
    {
        double d;
        uint32_t i[2];
    } u;
    #define RLN2 1.44269504088896340735
    double f;

    INF_TEST(0x7ff,0);
    INF_TEST(0xfff,0);
    
    INF_TEST(0x7ff,1);
    INF_TEST(0xfff,1);
    
    f=0.0/0.0;
    printf("f=0.0/0.0,");
    check_double(f);
}

void test_const()
{
    printf("\nrun %s()\n",__func__);

    double f1,f2;
    const char *s1,*s2;
    
    s1="\"0.69314718055994530942\"";   printf("s1=\t%s\n",s1);
    f1=0.69314718055994530942;   printf("f1=\t%.13la\n",f1);
    f1=0x1.62e42fefa39efp-1;     printf("L_f1=\t%.18lf\n",f1);
    f1=0x1.62e42fefa39f0p-1;     printf("H_f1=\t%.18lf\n",f1);

    s2="\"1.44269504088896340735\"";    printf("s2=\t%s\n",s2);
    f2=1.44269504088896340735;    printf("f2=\t%.13la\n",f2);
    f2=0x1.71547652b82fep+0;   printf("L_f2=\t%.18lf\n",f2);
    f2=0x1.71547652b82ffp+0;   printf("H_f2=\t%.18lf\n",f2);
}

int main(int argc, char* argv[])
{
    test_float();
    test_const();
    print_const();
    return 0;
}
